import camera from '@ohos.multimedia.camera'
import deviceInfo from '@ohos.deviceInfo'
import image from '@ohos.multimedia.image'
import media from '@ohos.multimedia.media'
import photoAccessHelper from '@ohos.file.photoAccessHelper'
import { UIContext } from '@ohos.arkui.UIContext';
import { Observed } from '@kit.ArkUI'
// import entry from 'libentry.so'
import Logger from '../utils/Logger';
import { BusinessError } from '@ohos.base'
import { Context, } from '@kit.ArkUI';

class CameraModeOptions {
  MODE_PHOTO: number
  MODE_VIDEO: number
}

class CameraSizeOptions {
  WIDTH: number
  HEIGHT: number
}

const CameraMode = {
  MODE_PHOTO: 0, // 拍照模式
  MODE_VIDEO: 1 // 录像模式
} as CameraModeOptions
const TAG: string = "CameraService"
const CameraSize = {
  // WIDTH: 1280,
  // HEIGHT: 720
  WIDTH: 1280,
  HEIGHT: 720
} as CameraSizeOptions

class profileConfig {
  audioBitrate: number
  audioChannels: number
  audioCodec: string
  audioSampleRate: number
  durationTime: number
  fileFormat: string
  videoBitrate: number
  videoCodec: string
  videoFrameWidth: number
  videoFrameHeight: number
  videoFrameRate: number
}

class locationConfig {
  latitude: number
  longitude: number
}

class videoConfig {
  audioSourceType: number
  videoSourceType: number
  profile: profileConfig
  url: string
  orientationHint: number
  location: locationConfig
  maxSize: number
  maxDuration: number
}

@Observed
export default class CameraService {
  private tag: string = 'CameraService'
  private context: Context = UIContext.getFocusedUIContext()?.getHostContext() as Context
  private context_: Context = UIContext.getFocusedUIContext()?.getHostContext() as Context
  private cameraManager: camera.CameraManager
  private cameras: Array<camera.CameraDevice>
  private cameraId: string = ''
  private cameraInput: camera.CameraInput
  private previewOutput: camera.PreviewOutput
  private previewShow: camera.PreviewOutput
  // private photoOutPut: camera.PhotoOutput = undefined
  private captureSession: camera.PhotoSession
  private mReceiver: image.ImageReceiver
  private photoUri: string = ''
  private fileAsset: photoAccessHelper.PhotoAsset
  private fd: number = -1
  private curMode = CameraMode.MODE_PHOTO
  private videoRecorder: media.VideoRecorder
  private videoOutput: camera.VideoOutput
  private handleTakePicture: (photoUri: string) => void
  private cameraOutputCapability: camera.CameraOutputCapability
  private cameraDeviceIndex: number
  private videoConfig: videoConfig = {
    audioSourceType: 1,
    videoSourceType: 0,
    profile: {
      audioBitrate: 48000,
      audioChannels: 2,
      audioCodec: 'audio/mp4v-es',
      audioSampleRate: 48000,
      durationTime: 1000,
      fileFormat: 'mp4',
      videoBitrate: 48000,
      videoCodec: 'video/mp4v-es',
      videoFrameWidth: 1280,
      videoFrameHeight: 720,
      videoFrameRate: 30
    },
    url: '',
    orientationHint: 0,
    location: {
      latitude: 30, longitude: 130
    },
    maxSize: 10000,
    maxDuration: 10000
  } as videoConfig

  constructor(context: Context) {
    let buffer = new ArrayBuffer(1382400);
    this.context = context
    this.mReceiver = image.createImageReceiver(CameraSize.WIDTH, CameraSize.HEIGHT, image.ImageFormat.JPEG, 8)
    Logger.info(this.tag, 'createImageReceiver')
    this.mReceiver.on('imageArrival', async () => {
      Logger.info(this.tag, 'imageArrival start')
      this.mReceiver.readNextImage((err, image) => {
        Logger.info(this.tag, 'readNextImage')
        if (err || image === undefined) {
          Logger.error(this.tag, 'failed to get valid image')
          return
        }
        image.getComponent(4, async (errMsg, img) => {
          // Logger.info(this.tag, 'getComponent')
          if (errMsg || img === undefined) {
            Logger.info(this.tag, 'failed to get valid buffer')
            return
          }
          if (img.byteBuffer) {

            // Logger.info(this.tag, `video buffer size: ${buffer.byteLength}`);
            // 长乘以宽*1.5
            buffer = img.byteBuffer.slice(0, 1382400);
            Logger.info(this.tag, `video buffer size: ${buffer.byteLength}`);
            // const view = new DataView(buffer, 0);
            // for(var i =0;i < 10; i++){
            //   Logger.info(this.tag, '1 buf: ' + i + ' '+ view.getUint8(i));
            // }
            if (buffer !== undefined) {
              if (this.context_ != undefined) {
                // Logger.info(this.tag, 'onFrameCallback');
                const flag: boolean = this.cameraDeviceIndex == 1 ? true : false;
                this.context_.onFrameCallback(buffer, flag, 21);
              }
            }
          } else {
            Logger.error(this.tag, 'img.byteBuffer is undefined')
          }
          await image.release();
        })
      })
    })


  }

  inInt(context: Any) {
    Logger.info(TAG, 'XC inInt')
    this.context_ = context
    Logger.info(TAG, 'this.context_-----４' + this.context_)
  }

  async clearInt() {
    Logger.info('clearInt')
    this.context_ = null
  }


  async preCameraLaunch() {
    // 创建CameraManager对象
    this.cameraManager = await camera.getCameraManager(this.context)
    Logger.info(this.tag, 'getCameraManager')
    // 获取相机列表
    this.cameras = await this.cameraManager.getSupportedCameras()
    Logger.info(this.tag, `get cameras ${this.cameras.length}`)
    if (this.cameras.length === 0) {
      Logger.info(this.tag, 'cannot get cameras')
      // return // todo 无法返回 null | undefined
    }
    // let cameraDevice = this.cameras[0]
    // 相机预热启动
    // if(this.cameraManager.isPrelaunchSupported(cameraDevice)) {kongzhi
    //   try {
    //     this.cameraManager.setPrelaunchConfig({
    //       cameraDevice: cameraDevice
    //     })
    //   } catch (error) {
    //     let err = error as BusinessError;
    //     console.error(`setPrelaunchConfig catch error: Code: ${err.code}, message: ${err.message}`)
    //   }
    // }
    // this.cameraManager.prelaunch()
  }


  async initCamera(surfaceId: string, cameraDeviceIndex: number = 0) {
    this.cameraDeviceIndex = cameraDeviceIndex;
    Logger.info(this.tag, 'initCamera')
    await this.releaseCamera()
    Logger.info(this.tag, `deviceInfo.deviceType = ${deviceInfo.deviceType}`)
    if (deviceInfo.deviceType === 'default') {
      this.videoConfig.videoSourceType = 1
    } else {
      this.videoConfig.videoSourceType = 0
    }
    // 创建CameraManager对象
    this.cameraManager = await camera.getCameraManager(this.context)
    Logger.info(this.tag, 'getCameraManager')
    // 获取相机列表
    this.cameras = await this.cameraManager.getSupportedCameras()
    Logger.info(this.tag, `get cameras ${this.cameras.length}`)
    if (this.cameras.length === 0) {
      Logger.info(this.tag, 'cannot get cameras')
      // return // todo 无法返回 null | undefined
    }
    let cameraDevice = this.cameras[cameraDeviceIndex]
    // 创建相机输入流
    this.cameraInput = await this.cameraManager.createCameraInput(cameraDevice)
    // 打开相机
    this.cameraInput.open()
    Logger.info(this.tag, 'createCameraInput')
    // 获取相机设备支持的输出流能力
    this.cameraOutputCapability = await this.cameraManager.getSupportedOutputCapability(cameraDevice)
    Logger.debug(this.tag, 'cameraOutputCapability: ' + JSON.stringify(this.cameraOutputCapability))
    let previewProfile = this.cameraOutputCapability.previewProfiles[0]
    previewProfile.size.height = CameraSize.HEIGHT
    previewProfile.size.width = CameraSize.WIDTH
    // 获取照片显示SurfaceId
    const mSurfaceId = await this.mReceiver.getReceivingSurfaceId()
    // 创建预览输出流,其中参数 surfaceId 参考上文 XComponent 组件，预览流为XComponent组件提供的surface
    this.previewShow = await this.cameraManager.createPreviewOutput(previewProfile, mSurfaceId)
    this.previewOutput = await this.cameraManager.createPreviewOutput(previewProfile, surfaceId)
    Logger.info(this.tag, 'createPreviewOutput')
    let photoProfile = this.cameraOutputCapability.photoProfiles[0]
    // 创建拍照输出流
    // try {
    //   this.photoOutPut = this.cameraManager.createPhotoOutput(photoProfile, mSurfaceId)
    // } catch (error) {
    //   Logger.error(this.tag, `createPhotoOutput failed: ${JSON.stringify(error)}`);
    // }
    //创建会话
    this.captureSession = await this.cameraManager.createCaptureSession()
    Logger.info(this.tag, 'createCaptureSession')
    // 开始配置会话
    await this.captureSession.beginConfig()
    Logger.info(this.tag, 'beginConfig')
    // 向会话中添加相机输入流
    await this.captureSession.addInput(this.cameraInput)
    // 向会话中添加预览输出流
    await this.captureSession.addOutput(this.previewOutput)
    await this.captureSession.addOutput(this.previewShow)
    // 向会话中添加拍照输出流
    // await this.captureSession.addOutput(this.photoOutPut)
    // 提交会话配置
    await this.captureSession.commitConfig()
    // 启动会话
    await this.captureSession.start()
    // 延时配流
    // this.previewShow.addDeferredSurface(surfaceId);
    // this.previewOutput.addDeferredSurface(surfaceId);
    Logger.info(this.tag, 'initCamera finished')
  }

  setTakePictureCallback(callback: (photoUri: string) => void) {
    this.handleTakePicture = callback
  }

  async takePicture() {
    Logger.info(this.tag, 'takePicture')
    if (this.curMode === CameraMode.MODE_VIDEO) {
      this.curMode = CameraMode.MODE_PHOTO
    }
    let photoSettings = {
      rotation: camera.ImageRotation.ROTATION_0,
      quality: camera.QualityLevel.QUALITY_LEVEL_MEDIUM,
      location: {
        // 位置信息，经纬度
        latitude: 12.9698,
        longitude: 77.7500,
        altitude: 1000
      },
      mirror: false
    }
    // await this.photoOutPut.capture(photoSettings)
    Logger.info(this.tag, 'takePicture done')
    AppStorage.setOrCreate('isRefresh', true)
  }

  async startVideo() {
    Logger.info(this.tag, 'startVideo begin')
    await this.captureSession.stop()
    await this.captureSession.beginConfig()
    if (this.curMode === CameraMode.MODE_PHOTO) {
      this.curMode = CameraMode.MODE_VIDEO
      // if (this.photoOutPut) {
      //   await this.captureSession.removeOutput(this.photoOutPut)
      //   this.photoOutPut.release()
      // }
    } else {
      if (this.videoOutput) {
        await this.captureSession.removeOutput(this.videoOutput)
      }
    }
    if (this.videoOutput) {
      await this.captureSession.removeOutput(this.videoOutput)
      await this.videoOutput.release()
    }
    this.videoRecorder = await media.createVideoRecorder()
    //TODO video URL
    this.videoConfig.url = `fd://${this.fd}`
    await this.videoRecorder.prepare(this.videoConfig)
    let videoId = await this.videoRecorder.getInputSurface()
    let videoProfile = this.cameraOutputCapability.videoProfiles[0];
    this.videoOutput = await this.cameraManager.createVideoOutput(videoProfile, videoId)
    await this.captureSession.addOutput(this.videoOutput)
    await this.captureSession.commitConfig()
    await this.captureSession.start()
    await this.videoOutput.start()
    await this.videoRecorder.start()
    Logger.info(this.tag, 'startVideo end')
  }

  async stopVideo() {
    Logger.info(this.tag, 'stopVideo called')
    await this.videoRecorder.stop()
    await this.videoOutput.stop()
    await this.videoRecorder.release()
    await this.fileAsset.close(this.fd)
  }

  async releaseCamera() {
    Logger.info(this.tag, 'releaseCamera')
    if (this.cameraInput) {
      await this.cameraInput.close()
    }
    if (this.previewOutput) {
      await this.previewOutput.release()
    }
    // if (this.photoOutPut) {
    //   await this.photoOutPut.release()
    // }
    if (this.videoOutput) {
      await this.videoOutput.release()
    }
    if (this.captureSession) {
      await this.captureSession.release()
    }
  }
}

